Apollo Federation仕様
#Apollo社 #GraphQL_Federation
概要
Apollo Federation仕様は、2019年にApollo社が策定したGraphQLマイクロサービス統合の標準仕様です。複数の独立したGraphQLサービス(Subgraph)を統合して、単一の統合GraphQLスキーマ(Supergraph)として提供するためのアーキテクチャパターンと技術仕様を定義しています。
最新はv2
バージョン体系
Apollo Federation v1(2019年)
初期仕様: 基本的な連合機能を提供
コアディレクティブ: @key、@extends、@external、@requires、@provides
エンティティベース設計: 分散オブジェクトの統合アプローチ
業界標準確立: マイクロサービス統合の事実上の標準として採用
Apollo Federation v2(2021年)
仕様改良: より柔軟で強力な連合機能
新ディレクティブ: @shareable、@inaccessible、@override、@composeDirective
後方互換性: v1からのスムーズな移行をサポート
簡素化: @extendsディレクティブが不要に
核心概念
1. Entity(エンティティ)
分散オブジェクトの基盤
定義: 複数のサブグラフ間で共有されるオブジェクト型
識別: @keyディレクティブによる一意識別子の定義
拡張: 異なるサブグラフでフィールドを追加可能
解決: Gateway層での自動的な参照解決
2. Subgraph(サブグラフ)
独立したGraphQLサービス
責任範囲: 特定のドメインに特化したスキーマとリゾルバー
自律性: 独立した開発・デプロイメント・スケーリング
連合対応: Federation Directivesによる統合準備
標準クエリ: _service、_entitiesの実装
3. Supergraph(スーパーグラフ)
統合されたスキーマ
生成: Schema Compositionプロセスによる自動生成
統一API: クライアントからは単一のGraphQLエンドポイント
型安全性: 厳密な型システム統合による整合性保証
進化管理: 段階的なスキーマ変更のサポート
Federation Directives(連合ディレクティブ)
Core Directives(v1)
@key - エンティティキー定義
code: (graphql)
type User @key(fields: "id") @key(fields: "email") {
id: ID!
email: String!
name: String!
}
一意識別子の定義
複数キーの指定可能
resolvable: falseで参照専用エンティティ定義
@extends - エンティティ拡張(v1)
code: (graphql)
type User @key(fields: "id") @extends {
id: ID! @external
orders: Order!!
}
他サブグラフのエンティティにフィールド追加
v2では@extendsディレクティブ不要
@external - 外部フィールド参照
code: (graphql)
type User @key(fields: "id") {
id: ID! @external
name: String! @external
fullProfile: Profile! @requires(fields: "name")
}
他サブグラフで定義されたフィールドの参照
現在のサブグラフでは解決しない
@requires - 依存フィールド指定
code: (graphql)
type User @key(fields: "id") {
id: ID! @external
name: String! @external
displayName: String! @requires(fields: "name")
}
フィールド解決に必要な外部フィールドを指定
Gatewayが自動的に依存フィールドを取得
@provides - 提供フィールド宣言
code: (graphql)
type Review @key(fields: "id") {
id: ID!
product: Product! @provides(fields: "name price")
}
このサブグラフが提供できる外部フィールドを宣言
パフォーマンス最適化のためのヒント
Advanced Directives(v2)
@shareable - 共有フィールド
code: (graphql)
type Product @key(fields: "id") {
id: ID!
name: String! @shareable
description: String!
}
複数サブグラフで同じフィールドを定義可能
統一的な実装が前提
@inaccessible - 非公開フィールド
code: (graphql)
type User @key(fields: "id") {
id: ID!
email: String!
internalId: String! @inaccessible
}
スーパーグラフから特定フィールドを隠蔽
段階的移行時の一時的な隠蔽に使用
@override - フィールド上書き
code: (graphql)
type Product @key(fields: "id") {
id: ID!
name: String! @override(from: "ProductsV1")
}
他サブグラフのフィールド実装を上書き
段階的移行とサービス移管に活用
@composeDirective - カスタムディレクティブ合成
code: (graphql)
directive @auth(role: String!) on FIELD_DEFINITION
extend schema @composeDirective(name: "@auth")
type User @key(fields: "id") {
id: ID!
sensitiveData: String! @auth(role: "ADMIN")
}
カスタムディレクティブをスーパーグラフに統合
横断的関心事の統一的な表現
Schema Composition(スキーマ合成)
合成プロセス
1. サブグラフ収集: 各サブグラフのSDLを収集
2. 妥当性検証: Federation Directivesの整合性チェック
3. エンティティ統合: 同じ@keyを持つエンティティの統合
4. 型システム統合: 型の競合解決と統一
5. スーパーグラフ生成: 最終的な統合スキーマの生成
統合ルール
エンティティ統合:
同じ@keyを持つエンティティは自動統合
フィールドは各サブグラフから集約
型の競合は厳密にチェック
型システム統合:
Enumは値の和集合
InterfaceとImplementationの一貫性
Union型の拡張
Breaking Changes判定:
エンティティキーの変更
必須フィールドの削除
型の根本的変更
Query Planning と Execution
Query Planning
プロセス:
1. クエリ分析: クライアントクエリの構造解析
2. エンティティ特定: 必要なエンティティの識別
3. サブグラフマッピング: 各フィールドの所有サブグラフ特定
4. 依存関係解決: @requiresによる依存関係の処理
5. 実行計画生成: 最適な実行順序の決定
最適化戦略:
並列実行可能な部分の特定
バッチ処理によるN+1問題の回避
キャッシュ戦略の適用
Query Execution
Entity Resolution:
code: (graphql)
# _entitiesクエリによるエンティティ解決
{
_entities(representations: [
{__typename: "User", id: "1"}
]) {
... on User {
orders {
total
}
}
}
}
Reference Resolver:
code: (javascript)
const resolvers = {
User: {
__resolveReference(reference) {
return getUserById(reference.id);
}
}
};
サブグラフ実装要件
必須クエリ
_service クエリ:
code: (graphql)
type Query {
_service: _Service!
}
type _Service {
sdl: String! # サブグラフのSDL
}
_entities クエリ:
code: (graphql)
type Query {
_entities(representations: _Any!!): _Entity!
}
scalar _Any
union _Entity = User | Product | Order
Reference Resolver実装
各エンティティにReference Resolverを実装
表現オブジェクトから完全なエンティティを解決
パフォーマンス最適化(DataLoader等)の適用
制約と考慮事項
設計制約
循環依存の禁止: サブグラフ間の循環参照は不可
エンティティキーの一意性: 同一エンティティの@keyは一貫性が必要
型の整合性: 競合する型定義の厳密なチェック
パフォーマンス考慮
N+1問題: DataLoaderパターンによる解決
ネットワーク遅延: 複数サブグラフへのアクセス最適化
Query複雑度: 深いネストや大量フィールドの制限
セキュリティ制約
認証情報の伝播: サブグラフ間での認証コンテキスト共有
フィールドレベル認可: きめ細かいアクセス制御の実装
機密情報の保護: @inaccessibleによる情報隠蔽
参照
Apollo Federation Subgraph Specification - Apollo GraphQL Docs